package com.glsc.ngateway.platform.service.itflow.flowstrategy.cmdb.partIn;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormCPUInDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormDiskInDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormMemoryInDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormPartInDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.task.doTaskParam.AbstractFlowSearchParamDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.cmdb.PartInTaskFormDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.cmdb.domainDto.FlowFormPartInDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.AppEhrResponse;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.platform.dto.user.UserLeadersDto;
import com.glsc.ngateway.common.base.converter.platform.*;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.FlowPushOaLog;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.cmdb.*;
import com.glsc.ngateway.common.base.domain.sqlserver.glsec.TAmEhrEmpEntity;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskParamEnum;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.flow.cmdb.*;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.AbstractItFlowStrategy;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.cmdb.partIn.taskPostHandler.IPartInTaskPostHandlerAudit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhengyr
 * @date 2023/8/2-15:22
 */
@Component
public class PartInFlowStrategy extends AbstractItFlowStrategy<FlowFormPartInDto, PartInTaskFormDto> {
    private Map<String, IPartInTaskPostHandlerAudit> taskPostHandlerMap;

    @Autowired
    FlowFormPartInRepo flowFormPartInRepo;
    @Autowired
    FlowFormCPUInDetailRepo cpuInDetailRepo;
    @Autowired
    FlowFormMemoryInDetailRepo memoryInDetailRepo;
    @Autowired
    FlowFormDiskInDetailRepo diskInDetailRepo;
    @Autowired
    FlowFormPartInDetailRepo partInDetailRepo;
    @Autowired
    private UserService userService;

    @Autowired
    public void setTaskPostHandlerMap(List<IPartInTaskPostHandlerAudit> taskPostHandlerList) {
        this.taskPostHandlerMap = taskPostHandlerList.stream()
                .collect(Collectors.toMap(IPartInTaskPostHandlerAudit::getTaskDefinitionKey, handler -> handler));
    }

    @Override
    protected Map getTaskPassMap() {
        return taskPostHandlerMap;
    }

    @Override
    protected Map getTaskRejectMap() {
        return taskPostHandlerMap;
    }

    @Override
    public ITFlowEnum getFlowEnum() {
        return ITFlowEnum.CMDB_PART_IN;
    }

    @Override
    public List<String> pageProcessId(AbstractFlowSearchParamDto param, Pageable pageable) {
        return null;
    }

    @Override
    public PartInTaskFormDto saveOrUpdateForm(PartInTaskFormDto flowableForm) {
        if (StrUtil.isEmpty(flowableForm.getProcessId())) {
            throw PlatformException.error("没有流程processId,无法保存流程数据", false, false);
        }
        //保存流程主表单数据
        FlowFormPartIn oldData = flowFormPartInRepo.findByProcessId(flowableForm.getProcessId());
        if (Objects.nonNull(oldData)) {
            flowableForm.getFormMainData().setId(oldData.getId());
        }
        flowFormPartInRepo.save(Objects.requireNonNull(FlowFormPartInConverter.dto2Do(flowableForm.getFormMainData())));
        //保存新增的cpu/内存/硬盘/配件数据到流程表单子表。先删除已有processId的全部数据，再插入
        saveAllDetailList(flowableForm.getProcessId(), flowableForm);

        return flowableForm;
    }

    @Override
    public PartInTaskFormDto findFormByProcessId(String processId) {
        PartInTaskFormDto flowableForm = new PartInTaskFormDto();
        FlowFormPartIn formMainDataDo = flowFormPartInRepo.findByProcessId(processId);
        if (Objects.isNull(formMainDataDo)) {
            flowableForm.setFormMainData(new FlowFormPartInDto());
        } else {
            flowableForm.setFormMainData(FlowFormPartInConverter.do2Dto(formMainDataDo));
            flowableForm.setCpuInDataList(FlowFormCPUInDetailConverter.do2Dto(cpuInDetailRepo.findAllByprocessId(processId)));
            flowableForm.setMemoryInDataList(FlowFormMemoryInDetailConverter.do2Dto(memoryInDetailRepo.findAllByprocessId(processId)));
            flowableForm.setDiskInDataList(FlowFormDiskInDetailConverter.do2Dto(diskInDetailRepo.findAllByprocessId(processId)));
            flowableForm.setPartInDataList(FlowFormPartInDetailConverter.do2Dto(partInDetailRepo.findAllByprocessId(processId)));
        }
        return flowableForm;
    }

    /**
     * 前端规格数据保存到流程子表
     *
     * @throws Exception
     */
    private void saveAllDetailList(String processId, PartInTaskFormDto flowableForm) {
        //先删除所有当前流程的子表数据
        cpuInDetailRepo.deleteAll(cpuInDetailRepo.findAllByprocessId(processId));
        memoryInDetailRepo.deleteAll(memoryInDetailRepo.findAllByprocessId(processId));
        diskInDetailRepo.deleteAll(diskInDetailRepo.findAllByprocessId(processId));
        partInDetailRepo.deleteAll(partInDetailRepo.findAllByprocessId(processId));
        List<FlowFormCPUInDetailDto> cpuInDataList = flowableForm.getCpuInDataList();
        List<FlowFormMemoryInDetailDto> memoryInDataList = flowableForm.getMemoryInDataList();
        List<FlowFormDiskInDetailDto> diskInDataList = flowableForm.getDiskInDataList();
        List<FlowFormPartInDetailDto> partInDataList = flowableForm.getPartInDataList();
        //再插入当前提交的数据
        if (!CollectionUtils.isEmpty(cpuInDataList)) {
            cpuInDetailRepo.saveAll(cpuInDataList.stream()
                    .map(h -> {
                        FlowFormCPUInDetail domain = FlowFormCPUInDetailConverter.dto2Do(h);
                        domain.setProcessId(flowableForm.getProcessId());
                        return domain;
                    })
                    .collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(memoryInDataList)) {
            memoryInDetailRepo.saveAll(memoryInDataList.stream()
                    .map(h -> {
                        FlowFormMemoryInDetail domain = FlowFormMemoryInDetailConverter.dto2Do(h);
                        domain.setProcessId(flowableForm.getProcessId());
                        return domain;
                    })
                    .collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(diskInDataList)) {
            diskInDetailRepo.saveAll(diskInDataList.stream()
                    .map(h -> {
                        FlowFormDiskInDetail domain = FlowFormDiskInDetailConverter.dto2Do(h);
                        domain.setProcessId(flowableForm.getProcessId());
                        return domain;
                    })
                    .collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(partInDataList)) {
            partInDetailRepo.saveAll(partInDataList.stream()
                    .map(h -> {
                        FlowFormPartInDetail domain = FlowFormPartInDetailConverter.dto2Do(h);
                        domain.setProcessId(flowableForm.getProcessId());
                        return domain;
                    })
                    .collect(Collectors.toList()));
        }
    }


    @Resource
    private IFeignLdapService ehrService;

    /**
     * 流程节点，发起时动态指定节点处理人
     */
    @Override
    protected Map<String, List<String>> initDefaultTaskUserGroup(PlatformUserDto creator) throws PlatformException {
        AppEhrResponse staffRes = ehrService.getLdapEhrEmp(creator.getUsername(), null, false);
        TAmEhrEmpEntity staffEntity;
        if (Objects.isNull(staffRes) || staffRes.getStatus() != 0) {
            throw PlatformException.error(String.format("未找到员工%s信息", creator.getUsername()));
        } else {
            staffEntity = JSONObject.parseObject(JSONObject.toJSONString(staffRes.getData()), TAmEhrEmpEntity.class);
        }


        Map<String, List<String>> taskAssignee = new HashMap<>(16);
        UserLeadersDto userLeadersDto = userService.getDirectLeaderAndPrimaryDepartmentLeader(creator);
        if (CollectionUtils.isEmpty(userLeadersDto.getDirectLeaders())) {
            throw PlatformException.error("未找到直属上级", false, false);
        }
        //1、发起人
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_IN_FLOW_BEGIN_TASK_ASSIGNMENTS.getName(), Arrays.asList(creator.getUsername()));
        //2.上级领导审批
        //taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_IN_FLOW_LEADER_TASK_ASSIGNMENTS.getName(), userLeadersDto.getDirectLeaders());
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_IN_FLOW_LEADER_TASK_ASSIGNMENTS.getName(), Arrays.asList(staffEntity.getReportto()));
        //3、发起人确认
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_IN_FLOW_CREATOR_AUDIT_TASK_ASSIGNMENTS.getName(), Arrays.asList(creator.getUsername()));
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_IN_FLOW_SYNC_OA_TASK_ASSIGNMENTS.getName(), Arrays.asList("admin"));
        return taskAssignee;
    }

    @Override
    public void endFromOaFlow(FlowPushOaLog log, String description) throws Exception {
        taskPostHandlerMap.get(log.getTaskKey()).endFromOaFlow(log, description);
    }
}
